package com.jjtm.common.core.utils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

/**
 * 日期工具类
 *
 * @author wangbaofeng
 */
public class DateUtil {

    /**
     * yyyyMM
     **/
    public static final String DATE_JFP_STR = "yyyyMM";
    /**
     * yyyy-MM-dd HH:mm:ss
     **/
    public static final String DATE_FULL_STR = "yyyy-MM-dd HH:mm:ss";

    /**
     * yyyy-MM-dd HH:mm
     **/
    public static final String DATE_FULL_NOS_STR = "yyyy-MM-dd HH:mm";

    /**
     * yyyy-MM-dd
     **/
    public static final String DATE_SMALL_STR = "yyyy-MM-dd";
    /**
     * yyMMddHHmmss
     **/
    public static final String DATE_KEY_STR = "yyyyMMddHHmmss";

    /**
     * 日期转换为字符串 格式自定义
     *
     * @param date   date
     * @param format format
     * @return String
     */
    public static String date2Str(Date date, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(date);
    }

    /**
     * 符合格式的字符串转换为java.util.Date
     *
     * @param source source
     * @param format format
     * @return java.util.Date
     */
    public static Date str2Date(String source, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        try {
            return sdf.parse(source);
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * 将时间戳转换为Date
     *
     * @param time time
     * @return Date
     */
    public static Date getDate(String time) {
        long t = Long.parseLong(time);
        return new Date(t * 1000);
    }

    /**
     * 使用预设格式提取字符串日期
     *
     * @param strDate 日期字符串
     * @return Date
     */
    public static Date parse(String strDate) {
        return parse(strDate, DATE_FULL_STR);
    }

    /**
     * 使用用户格式提取字符串日期
     *
     * @param strDate 日期字符串
     * @param pattern 日期格式
     * @return Date
     */
    public static Date parse(String strDate, String pattern) {
        SimpleDateFormat df = new SimpleDateFormat(pattern);
        try {
            return df.parse(strDate);
        } catch (ParseException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 将Date转换为时间戳
     *
     * @param date date
     * @return long
     */
    public static long getTime(Date date) {
        return date.getTime() / 1000;
    }

    public static int getDay(Date d) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(d);
        return cal.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * 日期转Date
     *
     * @param s "yyyy-mm-dd" 形式的日期的 String 对象
     * @return Date
     */
    public static Date valueOf(String s) {
        final int yearLength = 4;
        final int monthLength = 2;
        final int dayLength = 2;
        final int maxMonth = 12;
        final int maxDay = 31;
        int firstDash, secondDash;
        int threeDash = 0;
        int fourDash = 0;
        String colon = ":";
        Date d = null;
        if (s == null) {
            throw new IllegalArgumentException();
        }
        firstDash = s.indexOf('-');
        secondDash = s.indexOf('-', firstDash + 1);
        if (s.contains(colon)) {
            threeDash = s.indexOf(colon);
            fourDash = s.indexOf(colon, threeDash + 1);
        }
        if ((firstDash > 0) && (secondDash > 0) && (secondDash < s.length() - 1)) {
            String yyyy = s.substring(0, firstDash);
            String mm = s.substring(firstDash + 1, secondDash);
            String dd = "";
            String hh = "";
            String min = "";
            String ss = "";
            if (s.contains(colon)) {
                dd = s.substring(secondDash + 1, threeDash - 3);
                hh = s.substring(threeDash - 2, threeDash);
                min = s.substring(threeDash + 1, fourDash);
                ss = s.substring(fourDash + 1);
            } else {
                dd = s.substring(secondDash + 1);
            }
            if (yyyy.length() == yearLength && mm.length() == monthLength && dd.length() == dayLength) {
                int year = Integer.parseInt(yyyy);
                int month = Integer.parseInt(mm);
                int day = Integer.parseInt(dd);
                int hour = 0;
                int minute = 0;
                int second = 0;
                if (s.contains(colon)) {
                    hour = Integer.parseInt(hh);
                    minute = Integer.parseInt(min);
                    second = Integer.parseInt(ss);
                }
                if (month >= 1 && month <= maxMonth) {
                    int maxDays = maxDay;
                    switch (month) {
                        case 2:
                            boolean b = (year % 4 == 0 && (year % 100 > 0)) || (year % 400 == 0);
                            if (b) {
                                maxDays = maxDay - 2;
                            } else {
                                maxDays = maxDay - 3;
                            }
                            break;
                        case 4:
                        case 6:
                        case 9:
                        case 11:
                            maxDays = maxDay - 1;
                            break;
                        default:
                    }
                    if (day >= 1 && day <= maxDays) {
                        Calendar cal = Calendar.getInstance();
                        cal.set(year,
                                month - 1,
                                day,
                                hour,
                                minute,
                                second);
                        cal.set(Calendar.MILLISECOND, 0);
                        d = cal.getTime();
                    }
                }
            }
        }
        if (d == null) {
            throw new IllegalArgumentException();
        }
        return d;
    }

    /**
     * 前/后?分钟
     *
     * @param date   date
     * @param minute minute
     * @return Date
     */
    public static Date rollMinute(Date date, Long minute) {
        return new Date(date.getTime() + minute * 60 * 1000);
    }

    /**
     * 前/后?天
     *
     * @param date date
     * @param day  day
     * @return Date
     */
    public static Date rollDay(Date date, int day) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DAY_OF_MONTH, day);
        return cal.getTime();
    }

    /**
     * 前/后?月
     *
     * @param date date
     * @param mon  mon
     * @return Date
     */
    public static Date rollMon(Date date, int mon) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MONTH, mon);
        return cal.getTime();
    }

    /**
     * 前/后?年
     *
     * @param date date
     * @param year year
     * @return Date
     */
    public static Date rollYear(Date date, int year) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.YEAR, year);
        return cal.getTime();
    }

    public static Date rollDate(Date d, int year, int mon, int day) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(d);
        cal.add(Calendar.YEAR, year);
        cal.add(Calendar.MONTH, mon);
        cal.add(Calendar.DAY_OF_MONTH, day);
        return cal.getTime();
    }

    /**
     * 获取当前时间-时间戳字符串
     *
     * @return String
     */
    public static String getNowTimeStr() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }

    /**
     * 功能描述:获取当前时间 yyyy-MM-dd HH:mm:ss
     *
     * @author wangbaofeng
     * @date 2017年6月19日
     */
    public static String getNow() {
        SimpleDateFormat df = new SimpleDateFormat(DATE_FULL_STR);
        return df.format(new Date());
    }

    /**
     * 功能描述:按指定格式获取当前系统时间
     *
     * @param format format
     * @return String
     * @author wangbaofeng
     * @date 2017年6月19日
     */
    public static String getNow(String format) {
        SimpleDateFormat df = new SimpleDateFormat(format);
        return df.format(new Date());
    }

    /**
     * 将Date转换为时间戳
     *
     * @param time time
     * @return String
     */
    public static String getTimeStr(Date time) {
        long date = time.getTime();
        return Long.toString(date / 1000);
    }

    public static String getTimeStr(LocalDateTime time) {

        Long str = time.toInstant(ZoneOffset.of("+8")).toEpochMilli();
        return String.valueOf(str);
    }

    public static String getTimeStr(String dateStr, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Date date;
        try {
            date = sdf.parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
            return "";
        }
        return DateUtil.getTimeStr(date);
    }

    /**
     * 获取给定时间字符串
     */
    public static String getTimeStr(Date date, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(date);
    }

    public static Date getIntegralTime() {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    public static Date getLastIntegralTime() {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    public static Date getLastSecIntegralTime(Date d) {
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(d.getTime());
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    /**
     * 获取本周日的日期
     *
     * @return String
     */
    public static String getCurrentWeekday() {
        int mondayPlus = DateUtil.getMondayPlus();
        GregorianCalendar currentDate = new GregorianCalendar();
        currentDate.add(GregorianCalendar.DATE, mondayPlus + 6);
        Date monday = currentDate.getTime();

        DateFormat df = DateFormat.getDateInstance();
        return df.format(monday);
    }

    /**
     * 获得当前日期与本周日相差的天数
     *
     * @return int
     */
    private static int getMondayPlus() {
        Calendar cd = Calendar.getInstance();
        // 获得今天是一周的第几天，星期日是第一天，星期二是第二天......
        // 因为按中国礼拜一作为第一天所以这里减1
        int dayOfWeek = cd.get(Calendar.DAY_OF_WEEK) - 1;
        if (dayOfWeek == 1) {
            return 0;
        } else {
            return 1 - dayOfWeek;
        }
    }

    /**
     * 获得本周一的日期
     *
     * @return String
     */
    public static String getMondayOfWeek() {
        int mondayPlus = DateUtil.getMondayPlus();
        GregorianCalendar currentDate = new GregorianCalendar();
        currentDate.add(GregorianCalendar.DATE, mondayPlus);
        Date monday = currentDate.getTime();

        DateFormat df = DateFormat.getDateInstance();
        return df.format(monday);
    }

    /**
     * 获取当前月第一天：
     */
    public static String getFirstDayOfMonth() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Calendar c = Calendar.getInstance();
        c.add(Calendar.MONTH, 0);
        // 设置为1号,当前日期既为本月第一天
        c.set(Calendar.DAY_OF_MONTH, 1);
        return format.format(c.getTime());
    }

    /**
     * 获取当月最后一天
     */
    public static String getLastDayOfMonth() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Calendar ca = Calendar.getInstance();
        ca.set(Calendar.DAY_OF_MONTH, ca.getActualMaximum(Calendar.DAY_OF_MONTH));
        return format.format(ca.getTime());
    }

    /**
     * 日期月份处理
     *
     * @param d     时间
     * @param month 相加的月份，正数则加，负数则减
     * @return Date
     */
    public static Date timeMonthManage(Date d, int month) {
        Calendar rightNow = Calendar.getInstance();
        rightNow.setTime(d);
        rightNow.add(Calendar.MONTH, month);
        return rightNow.getTime();
    }

    /**
     * 获取指定年月的最后一天
     *
     * @param yearTime  指定年
     * @param monthTime 指定月
     * @return Date
     */
    public static Date monthLastDay(int yearTime, int monthTime) {
        Calendar cal = Calendar.getInstance();
        cal.set(yearTime, monthTime, 0, 23, 59, 59);
        return cal.getTime();
    }

    /**
     * 获取指定年月的第一天
     *
     * @param yearTime  指定年
     * @param monthTime 指定月
     * @return Date
     */
    public static Date monthFirstDay(int yearTime, int monthTime) {
        Calendar cal = Calendar.getInstance();
        cal.set(yearTime,
                monthTime - 1,
                1,
                0,
                0,
                0);
        return cal.getTime();
    }

    /**
     * 获取指定时间月的第一天
     *
     * @param d 指定时间，为空代表当前时间
     * @return Date
     */
    public static Date currMonthFirstDay(Date d) {
        Calendar cal = Calendar.getInstance();
        if (d != null) {
            cal.setTime(d);
        }
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMinimum(Calendar.DAY_OF_MONTH));
        cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DATE), 0, 0, 0);
        return cal.getTime();
    }

    /**
     * 获取指定时间月的最后一天
     *
     * @param d 指定时间，为空代表当前时间
     * @return Date
     */
    public static Date currMonthLastDay(Date d) {
        Calendar cal = Calendar.getInstance();
        if (d != null) {
            cal.setTime(d);
        }
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
        cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DATE), 23, 59, 59);
        return cal.getTime();
    }

    /**
     * 获取指定时间的年
     *
     * @param date 指定时间
     * @return int
     */
    public static int getTimeYear(Date date) {
        if (date == null) {
            date = new Date();
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.YEAR);
    }

    /**
     * 获取指定时间的月
     *
     * @param date 指定时间
     * @return int
     */
    public static int getTimeMonth(Date date) {
        if (date == null) {
            date = new Date();
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.MONTH) + 1;
    }

    /**
     * 获取指定时间的天
     *
     * @param date 指定时间
     * @return int
     */
    public static int getTimeDay(Date date) {
        if (date == null) {
            date = new Date();
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.DATE);
    }

    public static Date getFirstSecIntegralTime(Date d) {
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(d.getTime());
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.MILLISECOND, 0);
        cal.set(Calendar.DATE, 0);
        return cal.getTime();
    }

    /**
     * 获取指定时间天的结束时间
     *
     * @param d d
     * @return Date
     */
    public static Date getDayEndTime(long d) {
        Date day = new Date(d);
        if (d <= 0) {
            day = new Date();
        }
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(day.getTime());
        cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DATE), 23, 59, 59);
        return cal.getTime();
    }

    /**
     * 获取指定时间天的开始时间
     *
     * @param d d
     * @return Date
     */
    public static Date getDayStartTime(long d) {
        Date day = new Date(d);
        if (d <= 0) {
            day = new Date();
        }
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(day.getTime());
        cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DATE), 0, 0, 0);
        return cal.getTime();
    }

    /**
     * 获取19位的格式时间
     *
     * @param dateStr dateStr
     * @return Date
     */
    public static Date getDateByFullDateStr(String dateStr) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            return sdf.parse(dateStr);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取10位的格式时间
     *
     * @param dateStr dateStr
     * @return Date
     */
    public static Date getDate10ByStr(String dateStr, String format) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(format);
            return sdf.parse(dateStr);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取两个时间的时间差分 功能描述：
     *
     * @param early early
     * @param late late
     * @return int 返回类型
     * @author chengdongdong
     * @date 2016年9月2日
     */
    public static int minuteBetween(Date early, Date late) {
        // 得到两个日期相差的分数
        return ((int) (early.getTime() / 1000) - (int) (late.getTime() / 1000)) / 60;
    }

    /**
     * 获取两个时间的时间差秒数 功能描述：
     *
     * @param early early
     * @param late late
     * @return int 返回类型
     * @author chengdongdong
     * @date 2016年9月2日
     */
    public static int secondBetween(Date early, Date late) {
        // 得到两个日期相差的秒数
        return ((int) (early.getTime() / 1000) - (int) (late.getTime() / 1000));
    }

    /**
     * 获取两个时间的时间差天数 功能描述：
     *
     * @param early early
     * @param late late
     * @return int 返回类型
     * @author chengdongdong
     * @date 2016年9月2日
     */
    public static int daysBetween(Date early, Date late) {

        Calendar calst = Calendar.getInstance();
        Calendar caled = Calendar.getInstance();
        calst.setTime(early);
        caled.setTime(late);
        // 设置时间为0时
        calst.set(Calendar.HOUR_OF_DAY, 0);
        calst.set(Calendar.MINUTE, 0);
        calst.set(Calendar.SECOND, 0);
        caled.set(Calendar.HOUR_OF_DAY, 0);
        caled.set(Calendar.MINUTE, 0);
        caled.set(Calendar.SECOND, 0);
        // 得到两个日期相差的天数
        return ((int) (caled.getTime().getTime() / 1000) - (int) (calst.getTime().getTime() / 1000)) / 3600 / 24;
    }

    /**
     * 获取两个时间的时间差年数 功能描述：
     *
     * @param early early
     * @param late late
     * @return int 返回类型
     * @author chengdongdong
     * @date 2016年9月2日
     */
    public static int yearsBetween(Date early, Date late) {

        Calendar calst = Calendar.getInstance();
        Calendar caled = Calendar.getInstance();
        calst.setTime(early);
        caled.setTime(late);
        // 设置时间为0时
        calst.set(Calendar.HOUR_OF_DAY, 0);
        calst.set(Calendar.MINUTE, 0);
        calst.set(Calendar.SECOND, 0);
        caled.set(Calendar.HOUR_OF_DAY, 0);
        caled.set(Calendar.MINUTE, 0);
        caled.set(Calendar.SECOND, 0);
        // 得到两个日期相差的天数
        return caled.get(Calendar.YEAR) - calst.get(Calendar.YEAR);
    }

    /**
     * 获取日期距离当前日期的秒数
     *
     * @param date 日期字符串
     * @return int
     */
    public static int countSecond(Date date) {
        long t = Calendar.getInstance().getTime().getTime();
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        long t1 = c.getTime().getTime();
        return (int) (t / 1000 - t1 / 1000);
    }

    /**
     * 获取当前日期是星期几<br>
     * 0-6 周日 -- 周六
     *
     * @param date date
     * @return w+1
     */
    public static int getWeekOfDate(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.DAY_OF_WEEK) - 1;
    }

    public static String getWeekOfDate(int day) {
        String[] weekDays = {"星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"};
        return weekDays[day - 1];
    }

    public static String secToTime(String ms) {
        int minute = Integer.parseInt(ms) / 1000 / 60;
        return Integer.toString(minute);
    }

    public static String formatTime(Long ms) {
        int ss = 1000;
        int mi = ss * 60;
        Integer hh = mi * 60;
        Integer dd = hh * 24;

        Long day = ms / dd;
        Long hour = (ms - day * dd) / hh;
        Long minute = (ms - day * dd - hour * hh) / mi;
        Long second = (ms - day * dd - hour * hh - minute * mi) / ss;
        Long milliSecond = ms - day * dd - hour * hh - minute * mi - second * ss;

        StringBuilder sb = new StringBuilder();
        if (day > 0) {
            sb.append(day).append("天");
        }
        if (hour > 0) {
            sb.append(hour).append("小时");
        }
        if (minute > 0) {
            sb.append(minute).append("分");
        }
        if (second > 0) {
            sb.append(second).append("秒");
        }
        if (milliSecond > 0) {
            sb.append(milliSecond).append("毫秒");
        }
        return sb.toString();
    }

}
